/*
 * Block device emulated in RAM
 *
 * Copyright (c) 2022, The littlefs authors.
 * Copyright (c) 2017, Arm Limited. All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include <stdint.h>
#include "lfs_flashbd.h"
#include "flash.h"

#define FLASH_BLOCK_SIZE FLASH_PAGE_SIZE
#define FLASHBD_BASE (FLASH_BASE_ADDR + FLASH_SIZE - FLASH_BLOCK_SIZE*16)
#define FLASHBD_END (FLASH_BASE_ADDR + FLASH_SIZE)
#define FLASHBD_BLOCK_OFF_TO_ADDR(block, off) (FLASHBD_BASE + FLASH_BLOCK_SIZE * (block) + (off))


int lfs_flashbd_read(const struct lfs_config *cfg, lfs_block_t block,
        lfs_off_t off, void *buffer, lfs_size_t size) {
    const uint32_t addr = FLASHBD_BLOCK_OFF_TO_ADDR(block, off);
    // check if read is valid
    LFS_ASSERT(FLASHBD_BASE <= addr && (addr + size) < FLASHBD_END);

    // read data
    flash_read(addr, buffer, size);    
    return 0;
}

int lfs_flashbd_prog(const struct lfs_config *cfg, lfs_block_t block,
        lfs_off_t off, const void *buffer, lfs_size_t size) {
   const uint32_t addr = FLASHBD_BLOCK_OFF_TO_ADDR(block, off);
   LFS_ASSERT(FLASHBD_BASE <= addr && (addr + size) < FLASHBD_END);
    // program data    
    return flash_write(addr, (uint32_t*)buffer, size/sizeof(uint32_t));
}

int lfs_flashbd_erase(const struct lfs_config *cfg, lfs_block_t block) {
    const uint32_t addr = FLASHBD_BLOCK_OFF_TO_ADDR(block, 0);
    LFS_ASSERT(FLASHBD_BASE <= addr && addr < FLASHBD_END);
    return flash_erase(addr, 1);
}

int lfs_flashbd_sync(const struct lfs_config *cfg) {
    // return flash_sync();
    flash_flush_icache();
    return 0;
}
